package com.tanfuqi.sicent.protocol

import com.tanfuqi.sicent.protocol.message.Message
import com.tanfuqi.sicent.protocol.message.objectMapper
import com.tanfuqi.sicent.protocol.message.toJson
import com.tanfuqi.sicent.protocol.util.DESUtil
import org.apache.mina.core.buffer.IoBuffer
import org.apache.mina.core.session.IoSession
import org.apache.mina.filter.codec.*
import org.apache.mina.util.Base64
import org.slf4j.LoggerFactory
import java.nio.ByteOrder
import org.apache.mina.filter.codec.ProtocolCodecFactory as ProtocolCodecFactoryInterface


object ProtocolCodecFactory : ProtocolCodecFactoryInterface {
    private val logger = LoggerFactory.getLogger(ProtocolCodecFactory::class.java)

    override fun getDecoder(p0: IoSession?): ProtocolDecoder =
            object : CumulativeProtocolDecoder() {
                override fun doDecode(session: IoSession, buffer: IoBuffer, out: ProtocolDecoderOutput): Boolean {
                    if (buffer.remaining() > 19) {
                        buffer.mark()
                        val message = Message()

                        buffer.order(ByteOrder.LITTLE_ENDIAN)
                        message.sign = buffer.int

                        val size = buffer.int
                        message.companyId = buffer.int
                        message.type = buffer.int

                        message.id = buffer.int
                        buffer.order(ByteOrder.BIG_ENDIAN)

                        if (size > 0) {
                            if (buffer.remaining() < size) {
                                buffer.reset()
                                return false
                            }
                            val body = ByteArray(size)
                            buffer.get(body)
                            println(message.type)
                            println(String(body))

                            val bodyJson = String(if (0x80008001L.toInt() != message.type) {
                                DESUtil.decrypt(Base64.decodeBase64(body), "D8D37704".toByteArray())
                            } else {
                                body
                            })
                            message.body= objectMapper.readValue(bodyJson,Any::class.java)
//                            message.setBody(bodyJson)
//                            message.body=Body()
                        }
                        out.write(message)

                        return buffer.remaining() > 0
                    }
                    return false
                }

            }

    val emptyBody = ByteArray(0)
    override fun getEncoder(p0: IoSession?): ProtocolEncoder =
            object : ProtocolEncoderAdapter() {
                override fun encode(p0: IoSession, p1: Any, out: ProtocolEncoderOutput) {

                    val message = p1 as Message
                    val bytes = when {
                        message.body == null -> emptyBody
                        0x80008001L.toInt() == message.type -> message.body!!.toJson().toByteArray()
                        else -> Base64.encodeBase64(DESUtil.encrypt(message.body!!.toJson().toByteArray(), "D8D37704".toByteArray()))
                    }
                    val buffer = IoBuffer.allocate(20 + bytes.size, false)
                    buffer.order(ByteOrder.LITTLE_ENDIAN)
                    buffer.putInt(message.sign)
                    buffer.putInt(bytes.size)
                    buffer.putInt(message.companyId)
                    buffer.putInt(message.type)
                    buffer.putInt(message.id)
                    buffer.order(ByteOrder.BIG_ENDIAN)
                    if (bytes.isNotEmpty())
                        buffer.put(bytes)
                    buffer.flip()

                    out.write(buffer)

                }

            }
}

